﻿using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using Map_Creator.MapInfo;
using Map_Creator.RedoUndo.Actions;

namespace Map_Creator.MainForm
{
    public partial class Main : Form
    {
        public Main()
        {
            InitializeComponent();

            SetStyle(ControlStyles.AllPaintingInWmPaint |
                ControlStyles.UserPaint | 
                ControlStyles.OptimizedDoubleBuffer, true);
            UpdateStyles();
            ActiveControl = TilesPanels;

            TilesPanels.SizeChanged += TilesPanel_SizeChanged;
            MapPanel.DrawModeChanged += MapPanel_DrawModeChanged;

            ActionHandler.MainActionHandler = RedoUndoStrip;
            RedoUndoStrip.OnRedoUndo += RedoUndoStrip_OnRedoUndo;

            var toolStrips = toolStripContainer1.TopToolStripPanel.Controls;
            var toolStripsArray = new ToolStrip[toolStrips.Count];
            foreach (ToolStrip toolStrip in toolStrips)
            {
                toolStripsArray[int.Parse((string)toolStrip.Tag) - 1] = toolStrip;
            }
            var posx = 3;
            const int pad = 3;
            foreach (var toolStrip in toolStripsArray)
            {
                toolStrip.Location = new Point(posx,0);
                posx += toolStrip.Size.Width + pad;
            }
        }

        void RedoUndoStrip_OnRedoUndo(RedoUndo.IRedoUndo actionHandler, RedoUndo.IAction action)
        {
            TilesPanels.ActiveTilesControl.Invalidate();
            MapPanel.Invalidate();
        }

        void MapPanel_DrawModeChanged(DrawMode mode)
        {
            foreach (var button in ModeToolStrip.Items.OfType<ToolStripButton>())
            {
                button.Checked = (string)button.Tag == MapPanel.DrawMode.ToString();
            }

            switch (MapPanel.DrawMode)
            {
                case DrawMode.Select:
                    ActionToolStrip.Show();
                    break;
                default:
                    ActionToolStrip.Hide();
                    break;
            }
        }

        private void TilesPanel_SizeChanged(object sender, EventArgs e)
        {
            if (TilesPanels.Size.Width != 0)
                splitContainer1.SplitterDistance =
                    TilesPanels.Size.Width;
        }

        private void OnKeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyValue >= (int)Keys.D0 && e.KeyValue<= (int)Keys.D9)
            {
                var level = (int)e.KeyData - (int)Keys.D0 - 1;
                if (!MapInfo.Map.SelectedMapFullyInitialized()) return;
                if (MapInfo.Map.SelectedMap.Levels > level)
                {
                    MapInfo.Map.SelectedMap.CurrentLayer = MapInfo.Map.SelectedMap[level];
                }
                return;
            }

            switch (e.KeyData)
            {
                case Keys.S:
                    ChangeMode(DrawMode.Select);
                    break;

                case Keys.D:
                    ChangeMode(DrawMode.Paint);
                    break;
            }
            if (e.Control)
            {
                if(e.KeyData.HasFlag(Keys.C))
                        Copy();
                if (e.KeyData.HasFlag(Keys.V))
                        Paste();
            }
        }

        private void SplitterMoved(object sender, SplitterEventArgs e)
        {
            // this hacks out the juggy gray line on the splitter
            if (TilesPanels.ActiveTilesControl.CanFocus)
                ((SplitContainer)sender).ActiveControl = TilesPanels.ActiveTilesControl;
        }

        private void splitContainer_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            ((SplitContainer)sender).SplitterDistance =
                        TilesPanels.ActiveTilesControl.Size.Width + SystemInformation.VerticalScrollBarWidth + SystemInformation.Border3DSize.Width * 2 + 8;

            if (TilesPanels.ActiveTilesControl.CanFocus)
                ((SplitContainer)sender).ActiveControl = TilesPanels.ActiveTilesControl;
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var saveDialog = new SaveFileDialog();
            if (saveDialog.ShowDialog() == DialogResult.OK)
            {
                SaveLoad.Save(MapInfo.Map.SelectedMap, saveDialog.FileName);
            }
        }

        private void loadToolStripMenuItem_Click(object sender, EventArgs e)
        {
#if !DEBUG
            try
            {
#endif
                var openDialog = new OpenFileDialog();
                if (openDialog.ShowDialog() == DialogResult.OK)
                {
                    MapInfo.Map.SelectedMap = SaveLoad.Load(openDialog.FileName);
                    if (MapInfo.Map.SelectedMap != null) TreeViewControl.MapTreeView.Nodes.Add(MapInfo.Map.SelectedMap.Node);
                }
#if !DEBUG
            }
            catch
            {
                MessageBox.Show("Error At Loading");
            }
#endif
        }

        private void OnModeChange(object sender, EventArgs e)
        {
            var senderButton = sender as ToolStripButton;

            ChangeMode((DrawMode)Enum.Parse(typeof(DrawMode),senderButton.Tag.ToString()));
        }

        private void ChangeMode(DrawMode mode)
        {
            MapPanel.DrawMode = mode;

            foreach (var button in ModeToolStrip.Items.OfType<ToolStripButton>())
            {
                button.Checked = (string) button.Tag == MapPanel.DrawMode.ToString();
            }

            MapPanel.Invalidate();

            switch (MapPanel.DrawMode)
            {
                case DrawMode.Data:
                    ActionToolStrip.Hide();
                    break;
                case DrawMode.Paint:
                    ActionToolStrip.Hide();
                    break;
                case DrawMode.Select:
                    ActionToolStrip.Show();
                    break;
            }
        }

        private ToolStrip hoveredToolStrip;

        private void LockToolStripMenuItem_Click(object sender, EventArgs e)
        {
            hoveredToolStrip.GripStyle = 
                hoveredToolStrip.GripStyle == ToolStripGripStyle.Visible ? 
                ToolStripGripStyle.Hidden : 
                ToolStripGripStyle.Visible;
        }

        private void OnToolStripEnter(object sender, EventArgs e)
        {
            hoveredToolStrip = sender as ToolStrip;
            (ToolStripMenuStrip.Items["Lock"] as ToolStripMenuItem).Checked = hoveredToolStrip.GripStyle == ToolStripGripStyle.Hidden;
        }

        private void FillToolStripButton_Click(object sender, EventArgs e)
        {
            if (!MapInfo.Map.SelectedMapFullyInitialized()) return;
            var invalidationRectangle = MapInfo.Map.SelectedMap.FillSelection();
            MapPanel.Invalidate(MathEx.ConvertToSystemRect(MapInfo.Map.SelectedMap.GetScreenSize(invalidationRectangle)));
        }

        private CopyGrid copyGrid;

        private void CopyStripButton_Click(object sender, EventArgs e)
        {
            Copy();
        }

        private void Copy()
        {
            if (!MapInfo.Map.SelectedMapFullyInitialized()) return;
            var map = MapInfo.Map.SelectedMap;
            copyGrid = CopyGrid.Copy(map.CurrentLayer.data, map.Selection.Rectangle);
        }

        private void PasteStripButton_Click(object sender, EventArgs e)
        {
            Paste();
        }

        private void Paste()
        {
            if (!MapInfo.Map.SelectedMapFullyInitialized()) return;
            if (copyGrid == null) return;
            var map = MapInfo.Map.SelectedMap;
            ActionHandler.MainActionHandler.AddActionAndExecute(new TilePaintAction(copyGrid, map.CurrentLayer,
                                                                                    map.Selection.Rectangle));
            // TODO: why wont it invalidate as expected?!
            MapPanel.Invalidate();
        }

        private void ShowGridButton_Click(object sender, EventArgs e)
        {
            var button = sender as ToolStripButton;
            button.Checked = !button.Checked;
            MapPanel.IsDrawGrid = button.Checked;
            MapPanel.Invalidate();
        }
            
        private void AnimationTick(object sender, EventArgs e)
        {
            AnimatedTile.GlobalFrame += 1;

            // Force Invalidation On EveryThing!!!
            TilesPanels.ActiveTilesControl.Invalidate();
            MapPanel.Invalidate();
        }

        private void StartAnimationsButton_Click(object sender, EventArgs e)
        {
            AnimationTimer.Start();
        }

        private void StopAnimationsButton_Click(object sender, EventArgs e)
        {
            AnimationTimer.Stop();
        }

        private void AnimationSpeedChange(object sender, EventArgs e)
        {
            var isRunning = AnimationTimer.Enabled;
            
            AnimationTimer.Stop();
            AnimationTimer.Interval = (int)(1000.0f / AnimationSpeedController.Value);
            FPSLabel.Text = "FPS: " + AnimationSpeedController.Value;
            if (isRunning)
                AnimationTimer.Start();
        }
    }
}